'''
Created on Apr 25, 2009

@author: caesar
'''

from telnetlib import Telnet
from fetcher import *
from state import *
import pickle

class NodeUnavailable(Exception):
  pass

class HuninProcessor (object):
  
  def __init__(self, \
               hosts     = [], \
               telnet    = Telnet, \
               storage   = MuninStorage, \
               fetcher   = MuninFetcher, \
               dumps_dir = './' \
               ):
    
    self.hosts = hosts # (address, port)
    self.telnet = telnet
    self.storage = storage
    self.fetcher = fetcher
    self.dumps_dir = dumps_dir
    

  def _process_host (self, host):
    address, port = host

    raw_filename   = self.dumps_dir+'/'+address+'_'+port.__str__()+'.raw'
    state_filename = self.dumps_dir+'/'+address+'_'+port.__str__()+'.state'

    try:
      try:
        tn = self.telnet(address, port)
      except: # FIXME: all exceptions! isn't really good
        raise NodeUnavailable()

      try:
        fd = open(raw_filename, 'r+')
      except IOError:
        fd = open (raw_filename, 'w')
        fd.close()
        fd = open(raw_filename, 'r+')
      
      
      storage = self.storage(fd)
      fetcher = self.fetcher(tn, storage, True)
      node_state = fetcher.get_node_state()

    except NodeUnavailable:
      node_state = MuninNodeState(False) # consider the node data empty if unavailable. 
                                         # will give good diff when it comes back on 

    try:
      fd2 = open (state_filename, 'r+')
      fd2.seek(0)
      unpicled_state = pickle.load(fd2)

    except IOError:
      fd2 = open (state_filename, 'w')
      unpicled_state = MuninNodeState(False)

    except EOFError:
      unpicled_state = MuninNodeState(False)

    except pickle.UnpicklingError:
      unpicled_state = MuninNodeState(False)
    
    diff = unpicled_state.diff(node_state)
    fd2.seek(0)
    pickle.dump(node_state, fd2, -1)
    
#    fd2.close()
#    fd.close()
    
    return diff
  
  def get_diffs (self):
    out = {}
    for host in self.hosts:
      diff = self._process_host(host)
      if not diff.is_different(): continue
      out[host] = diff
      
    return out
      
      
      
      
    